
/** <chessRules.pl> Raju rules for chess

This module define rules to play chess

@author Christian Arias
@license GPL
*/

%%      length(?List:list, +Length:int) is det.
%
%       True if TW is piece(tower,white)
%
%       @

:-include('base').
defPieceRW(RW):-RW=piece(rook,white).
defPieceHW(HW):-HW=piece(knight,white).
defPieceBW(BW):-BW=piece(bishop,white).
defPieceQW(QW):-QW=piece(queen,white).
defPieceKW(KW):-KW=piece(king,white).
defPiecePW(PW):-PW=piece(pawn,white).
defPieceRB(RB):-RB=piece(rook,black).
defPieceHB(HB):-HB=piece(knight,black).
defPieceBB(BB):-BB=piece(bishop,black).
defPieceQB(QB):-QB=piece(queen,black).
defPieceKB(KB):-KB=piece(king,black).
defPiecePB(PB):-PB=piece(pawn,black).
defPieceE(EE):-EE=empty.



ca(piece(Piece,Player),Ab):-pp(Piece,A),pp(Player,B),concat(A,B,Ab),!.
ca(empty,'__').

pp(rook,r).
pp(knight,n).
pp(bishop,b).
pp(queen,q).
pp(king,k).
pp(pawn,p).
pp(black,b).
pp(white,w).
%Printeable board
pr([],[]).
pr([H|T],[PH|TH]):-ca(H,PH),pr(T,TH).
pb1([],[]).
pb1([H|T],[AAH|TH]):-pr(H,AH),pb1(T,TH),concat_atom(AH,' ',AAH).
pb(BI,BO):-pb1(BI,BII),concat_atom(BII,'\n',BO).

adversary(white,black).
adversary(black,white).

%Available cell to be occupied by a piece. It could be empty or occupied by a opponent's piece
%
avalCell(T,X,Y,_):-getXY0(T,X,Y,empty).
avalCell(T,X,Y,C):-getXY0(T,X,Y,piece(_,Z)),adversary(C,Z).
%avalCell(T,X,Y,C):-getXY(T,X,Y,piece(P,Z)),adversary(C,Z),P\=r.

defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE):-defPieceRW(RW),defPieceHW(HW),defPieceBW(BW),defPieceQW(QW),defPieceKW(KW),defPiecePW(PW),
				defPieceRB(RB),defPieceHB(HB),defPieceBB(BB),defPieceQB(QB),defPieceKB(KB),defPiecePB(PB),
				defPieceE(EE).

%initialBoard(S,X):-defPieceRW(RW),defPieceHW(HW),defPieceBW(BW),defPieceQW(QW),defPieceKW(KW),defPiecePW(PW),
%				defPieceRB(RB),defPieceHB(HB),defPieceBB(BB),defPieceQB(QB),defPieceKB(KB),defPiecePB(PB),
%				defPieceE(EE),S=[wsc(y),wlc(y),bsc(y),blc(y)],
initialBoard(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
                  S=[wsc(y),wlc(y),bsc(y),blc(y),turn(white)],
               X=[[RW,HW,BW,QW,KW,BW,HW,RW],
				  [PW,PW,PW,PW,PW,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [PB,PB,PB,PB,PB,PB,PB,PB],
				  [RB,HB,BB,QB,KB,BB,HB,RB]].
				  
initialBoard2(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
                  S=[wsc(y),wlc(y),bsc(y),blc(y),turn(black)],
               X=[[RW,HW,BW,QW,KW,BW,HW,RW],
				  [PW,PW,PW,PW,EE,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,EE,EE,PW,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [PB,PB,PB,PB,PB,PB,PB,PB],
				  [RB,HB,BB,QB,KB,BB,HB,RB]].				  
				  
initialBoard1(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
                  S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[RW,HW,BW,QW,KW,BW,HW,RW],
				  [PW,PW,PW,PW,PW,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [PB,EE,EE,EE,EE,EE,EE,EE],
				  [EE,PB,PB,PB,PB,PB,PB,PB],
				  [RB,HB,BB,QB,KB,BB,HB,RB]].
				  				  
testBoardBSC1(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
				S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[RW,HW,BW,QW,KW,BW,HW,RW],
				  [PW,PW,PW,PW,PW,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [PB,PB,PB,PB,PB,PB,PB,PB],
				  [RB,HB,BB,QB,KB,EE,EE,RB]].
				  
testBoardBSC2(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
				S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[RW,HW,BW,QW,KW,BW,HW,RW],
				  [PW,PW,PW,PW,PW,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,RW,EE],
				  [PB,PB,PB,PB,PB,PB,EE,PB],
				  [RB,HB,BB,QB,KB,EE,EE,RB]].
				  
testBoardCMB(X,S):-defPieces(RW,HW,_,_,KW,PW,RB,HB,BB,QB,KB,PB,EE),
				S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[EE,EE,EE,EE,KW,EE,EE,RW],
				  [EE,EE,QB,EE,EE,EE,HW,PW],
				  [EE,EE,EE,EE,EE,HB,EE,EE],
				  [EE,EE,BB,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,RB,EE,EE,EE,EE],
				  [PB,EE,PB,PB,PB,PB,EE,PB],
				  [EE,EE,EE,EE,KB,EE,EE,RB]].				
				  
testBoardCMB2(X,S):-defPieces(RW,HW,_,_,KW,PW,RB,HB,BB,QB,KB,PB,EE),
				S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[EE,EE,EE,EE,KW,EE,EE,RW],
				  [EE,EE,QB,EE,EE,EE,HW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,BB,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,HB,EE],	               
				  [EE,EE,EE,RB,EE,EE,EE,EE],
				  [PB,EE,PB,PB,PB,PB,EE,PB],
				  [EE,EE,EE,EE,KB,EE,EE,RB]].				
				  
testBoardCAST2(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
				S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[RW,EE,EE,EE,KW,EE,EE,RW],
				  [PW,PW,PW,PW,PW,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [PB,PB,PB,PB,PB,PB,PB,PB],
				  [RB,EE,EE,EE,KB,EE,EE,RB]].  

testBoardPAWN(X,S):-defPieces(RW,HW,BW,QW,KW,PW,RB,HB,BB,QB,KB,PB,EE),
				S=[wsc(y),wlc(y),bsc(y),blc(y)],
               X=[[EE,EE,EE,KW,EE,EE,EE,EE],
				  [PW,PW,PW,PW,PW,PW,PW,PW],
				  [EE,EE,EE,EE,EE,EE,PB,EE],
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],	               
				  [EE,EE,EE,EE,EE,EE,EE,EE],
				  [PB,PB,PB,PB,PB,PB,PB,PB],
				  [RB,EE,EE,EE,KB,EE,EE,RB]].  				  
testBSC1(X1,Y1):-testBoardBSC1(S,B),moveKing(B,S,7,4,_,X1,Y1,black).
testBSC2(X1,Y1):-testBoardBSC2(S,B),moveKing(B,S,7,4,_,X1,Y1,black).
testXXX:-testBoardBSC2(S,B),threat(B,S,7,6,5,6,white).
				  
%Define when a cell it's outside of range				  
outside(X,_):-X>7,!.
outside(X,_):-X<0,!.
outside(_,Y):-Y>7,!.
outside(_,Y):-Y<0,!.

%limit(_,X,Y,DX,DY,_,X2,Y2):-AUXX is X + DX, AUXY is Y + DY,outside(AUXX,AUXY),X2=X,Y2=Y.
%limit(T,X,Y,DX,DY,Color,X2,Y2):-AUXX is X + DX, AUXY is Y + DY,getXY0(T,AUXX,AUXY,piece(_,W)), adversary(W,Color), X2=AUXX,Y2=AUXY.
%limit(T,X,Y,DX,DY,Color,X2,Y2):-AUXX is X + DX, AUXY is Y + DY,getXY0(T,AUXX,AUXY,piece(_,Color)),X2=X,Y2=Y.
%limit(T,X,Y,DX,DY,Color,X2,Y2):-AUXX is X + DX, AUXY is Y + DY,getXY0(T,AUXX,AUXY,empty),limit(T,AUXX,AUXY,DX,DY,Color,X2,Y2).

limit(T,X,Y,DX,DY,Color,X2,Y2):-AUXX is X + DX, AUXY is Y + DY,limit2(T,X,Y,DX,DY,Color,X2,Y2,AUXX,AUXY).
limit2(_,X,Y,_,_,_,X2,Y2,AUXX,AUXY):-outside(AUXX,AUXY),X2=X,Y2=Y,!.
limit2(T,_X,_Y,_DX,_DY,Color,X2,Y2,AUXX,AUXY):-getXY0(T,AUXX,AUXY,piece(_,W)), adversary(W,Color), X2=AUXX,Y2=AUXY,!.
limit2(T,X,Y,_DX,_DY,Color,X2,Y2,AUXX,AUXY):-getXY0(T,AUXX,AUXY,piece(_,Color)),X2=X,Y2=Y,!.
limit2(T,_,_,DX,DY,Color,X2,Y2,AUXX,AUXY):-getXY0(T,AUXX,AUXY,empty),limit(T,AUXX,AUXY,DX,DY,Color,X2,Y2).


limitRookRight(T,X,Y,Color,Y2):-limit(T,X,Y,0,1,Color,_,Y2).
limitRookLeft(T,X,Y,Color,Y2):-limit(T,X,Y,0,-1,Color,_,Y2).
limitRookUp(T,X,Y,Color,X2):-limit(T,X,Y,1,0,Color,X2,_).
limitRookDown(T,X,Y,Color,X2):-limit(T,X,Y,-1,0,Color,X2,_).

limitHorizontal(T,X,Y,L,R):-limitRookRight(T,X,Y,Color,R),limitRookLeft(T,X,Y,Color,L).
limitVertical(T,X,Y,U,D):-limitRookUp(T,X,Y,Color,U),limitRookDown(T,X,Y,Color,D).

limitBishopUpRight(T,X,Y,Color,X2,Y2):-limit(T,X,Y,1,1,Color,X2,Y2).
limitBishopDownRight(T,X,Y,Color,X2,Y2):-limit(T,X,Y,-1,1,Color,X2,Y2).
limitBishopUpLeft(T,X,Y,Color,X2,Y2):-limit(T,X,Y,1,-1,Color,X2,Y2).
limitBishopDownLeft(T,X,Y,Color,X2,Y2):-limit(T,X,Y,-1,-1,Color,X2,Y2).

%Pregunta si el player Player esta en jaque.
kingCheck(T,SS,Player,SX,SY):-adversary(Player,Adv),getCandidateMove(T,SS,SX,SY,_,TX,TY,Adv),getXY0(T,TX,TY,piece(king,Player)).

%Pregunta si el jugador Playes esta en jaqueMate
checkMate(T,SS,Player):-kingCheck(T,SS,Player,_,_),\+(getMove(T,SS,_,_,_,_,_,_,Player)).

%Player can reach cell SX,SY with piece at TX,TY
threat(T,SS,SX,SY,TX,TY,Player):-getCandidateMove(T,SS,TX,TY,_,SX,SY,Player).

%Move que funcionaba
singleMove(T,SX,SY,TX,TY,TB):-getXY0(T,SX,SY,P),rpMxT(T,TX,TY,P,Aux1),rpMxT(Aux1,SX,SY,empty,TB).
move(T,SX,SY,TX,TY,CP,TB):-singleMove(T,SX,SY,TX,TY,TEMP),complementaryMove(T,TEMP,SX,SY,TX,TY,CP,TB).

complementaryMove(_T,TEMP,SX,SY,TX,TY,CP,TB):-moveForCrowning(TEMP,SX,SY,TX,TY,CP,TB),!.
complementaryMove(T,_TEMP,SX,SY,TX,TY,_,TB):-moveForPassant(T,SX,SY,TX,TY,TB),!.
complementaryMove(_T,TEMP,SX,SY,TX,TY,_,TB):-moveForCastling(TEMP,SX,SY,TX,TY,TB),!.
complementaryMove(_T,TEMP,_,_,_,_,_,TEMP).

%moveForCastling(_TEMP,SX,SY,TX,TY,TB0):-moveForPassant(TB0,SX,SY,TX,TY,TB),moveForCrown(TB0,SX,SY,TX,TY,TB).
moveForCastling(T,_,_,TX,TY,TB):-getXY0(T,TX,TY,piece(P,_)),P \= king,TB = T,!.
moveForCastling(T,SX,SY,TX,TY,TB):-SY - TY > 1,singleMove(T,SX,0,TX,3,TB),!.
moveForCastling(T,SX,SY,TX,TY,TB):-SY - TY < -1,singleMove(T,SX,7,TX,5,TB),!.
%moveForCastling(T,_,_,_,_,T).

moveForPassant(SB,4,SY,5,TY,TB):-getXY0(SB,4,SY,piece(pawn,white)),getXY0(SB,5,TY,empty),SY \= TY, rpMxT(SB,4,TY,empty,TB),!.
moveForPassant(SB,3,SY,2,TY,TB):-getXY0(SB,3,SY,piece(pawn,black)),getXY0(SB,2,TY,empty),SY \= TY, rpMxT(SB,3,TY,empty,TB),!.
%moveForPassant(SB,_,_,_,_,SB).

moveForCrowning(SB,6,SY,7,TY,q,TB):-getXY0(SB,6,SY,piece(pawn,white)), rpMxT(SB,7,TY,piece(queen,white),TB),!.
moveForCrowning(SB,1,SY,0,TY,q,TB):-getXY0(SB,1,SY,piece(pawn,black)), rpMxT(SB,0,TY,piece(queen,black),TB),!.
%moveForCrown(SB,_,_,_,_,SB).

%getMove(T,SX,SY,TX,TY,Player):-ch_range(SX),ch_range(SY),movePawn(T,SX,SY,TX,TY,Player).
%getMove(T,SX,SY,TX,TY,Player):-ch_range(SX),ch_range(SY),moveKnight(T,SX,SY,TX,TY,Player).
%getMove(T,SX,SY,TX,TY,Player):-ch_range(SX),ch_range(SY),moveBishop(T,SX,SY,TX,TY,Player).
%getMove(T,SX,SY,TX,TY,Player):-ch_range(SX),ch_range(SY),moveRook(T,SX,SY,TX,TY,Player).
%%%%%%%%%%%%%%%%OJO%%%%%%%%%%%%%% 
getCandidateMove(T,SS,SX,SY,TS,TX,TY,Player):-ch_range(SX),ch_range(SY),getMovePiece(T,SS,SX,SY,TS,TX,TY,Player).

getMove(SB,SS,SX,SY,TB,TS,TX,TY,CP,Player):-getCandidateMove(SB,SS,SX,SY,TS,TX,TY,Player),move(SB,SX,SY,TX,TY,CB,TB),not(kingCheck(TB,TS,Player,_,_)).
%getMove(SB,SS,SX,SY,TB,TS,TX,TY,Player):-getCandidateMove(SB,SS,SX,SY,TS,TX,TY,Player),move(T,SX,SY,TX,TY,Aux),not(kingCheck(Aux,TS,Player,_,_)).

%getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-movePawn(T,SS,SX,SY,TS,TX,TY,Player).
%getMovePiece(T,SS,SX,SY,SS,TX,TY,Player):-moveKnight(T,SX,SY,TX,TY,Player).
%getMovePiece(T,SS,SX,SY,SS,TX,TY,Player):-moveBishop(T,SX,SY,TX,TY,Player).
%getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-moveRook(T,SS,SX,SY,TS,TX,TY,Player).
%getMovePiece(T,SS,SX,SY,SS,TX,TY,Player):-moveQueen(T,SX,SY,TX,TY,Player).
%getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-moveKing(T,SS,SX,SY,TS,TX,TY,Player).

%getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-movePawn(T,SS,SX,SY,TS,TX,TY,Player),!.
%getMovePiece(T,SS,SX,SY,SS,TX,TY,Player):-moveKnight(T,SX,SY,TX,TY,Player),!.
%getMovePiece(T,SS,SX,SY,SS,TX,TY,Player):-moveBishop(T,SX,SY,TX,TY,Player),!.
%getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-moveRook(T,SS,SX,SY,TS,TX,TY,Player),!.
%getMovePiece(T,SS,SX,SY,SS,TX,TY,Player):-moveQueen(T,SX,SY,TX,TY,Player),!.
%getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-moveKing(T,SS,SX,SY,TS,TX,TY,Player),!.

getMovePiece(T,_SS,SX,SY,_TS,_TX,_TY,_Player):-getXY0(T,SX,SY,empty),fail,!.
getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-getXY0(T,SX,SY,piece(pawn,Player)),!,movePawn2(T,SS,SX,SY,TS,TX,TY,Player).
getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-getXY0(T,SX,SY,piece(knight,Player)),!,moveKnight2(T,SX,SY,TX,TY,Player),remPassant(SS,TS).
getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-getXY0(T,SX,SY,piece(bishop,Player)),!,moveBishop2(T,SX,SY,TX,TY,Player),remPassant(SS,TS).
getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-getXY0(T,SX,SY,piece(rook,Player)),!,moveRook2(T,SS,SX,SY,TS0,TX,TY,Player),remPassant(TS0,TS).
getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-getXY0(T,SX,SY,piece(queen,Player)),!,moveQueen2(T,SX,SY,TX,TY,Player),remPassant(SS,TS).
getMovePiece(T,SS,SX,SY,TS,TX,TY,Player):-getXY0(T,SX,SY,piece(king,Player)),!,moveKing2(T,SS,SX,SY,TS0,TX,TY,Player),remPassant(TS0,TS).
				  
%movePawn(T,SS,X,Y,SS,X1,Y1,black):-getXY0(T,X,Y,piece(pawn,black)), X1 is X-1, ch_range(X1), getXY0(T,X1,Y,empty), Y1 is Y.
%movePawn(T,SS,6,Y,SS,X1,Y1,black):-getXY0(T,6,Y,piece(pawn,black)), X1 is 4, getXY0(T,5,Y,empty), getXY0(T,4,Y,empty), Y1 is Y.
%movePawn(T,SS,X,Y,SS,X1,Y1,black):-getXY0(T,X,Y,piece(pawn,black)), X1 is X-1, Y1 is Y+1, ch_range(X1), getXY0(T,X1,Y1,piece(_,white)).
%movePawn(T,SS,X,Y,SS,X1,Y1,black):-getXY0(T,X,Y,piece(pawn,black)), X1 is X-1, Y1 is Y-1, ch_range(X1), getXY0(T,X1,Y1,piece(_,white)).

movePawn(T,SS,X,Y,SS,X1,Y1,Color):-getXY0(T,X,Y,piece(pawn,Color)),!,movePawn2(T,SS,X,Y,SS,X1,Y1,Color).

movePawn2(T,SS,X,Y,TS,X1,Y1,black):- X1 is X-1, ch_range(X1), getXY0(T,X1,Y,empty), Y1 is Y, remPassant(SS,TS).
movePawn2(T,SS,6,Y,TS,X1,Y1,black):- X1 is 4, getXY0(T,5,Y,empty), getXY0(T,4,Y,empty), Y1 is Y, remPassant(SS,TS0),addPassant(TS0,X1,Y1,TS).
movePawn2(T,SS,X,Y,TS,X1,Y1,black):- X1 is X-1, Y1 is Y+1, ch_range(X1), getXY0(T,X1,Y1,piece(_,white)), remPassant(SS,TS).
movePawn2(T,SS,X,Y,TS,X1,Y1,black):- X1 is X-1, Y1 is Y-1, ch_range(X1), getXY0(T,X1,Y1,piece(_,white)), remPassant(SS,TS).
%Captura al paso
movePawn2(_,SS,3,Y,TS,X1,Y1,black):- Y1 is Y-1, member(ep(Y1),SS), X1 is 5  , remPassant(SS,TS).
movePawn2(_,SS,3,Y,TS,X1,Y1,black):- Y1 is Y+1, member(ep(Y1),SS), X1 is 5  , remPassant(SS,TS).

%Falta hacer el movimiento de captura al paso para los dos colores
%movePawn(T,SS,X,Y,SS,X1,Y1,white):-getXY0(T,X,Y,piece(pawn,white)), X1 is X+1, ch_range(X1), getXY0(T,X1,Y,empty), Y1 is Y.
%movePawn(T,SS,1,Y,SS,X1,Y1,white):-getXY0(T,1,Y,piece(pawn,white)), X1 is 3, getXY0(T,2,Y,empty), getXY0(T,3,Y,empty), Y1 is Y.
%movePawn(T,SS,X,Y,SS,X1,Y1,white):-getXY0(T,X,Y,piece(pawn,white)), X1 is X+1, Y1 is Y-1, ch_range(X1), getXY0(T,X1,Y1,piece(_,black)).
%movePawn(T,SS,X,Y,SS,X1,Y1,white):-getXY0(T,X,Y,piece(pawn,white)), X1 is X+1, Y1 is Y+1, ch_range(X1), getXY0(T,X1,Y1,piece(_,black)).

movePawn2(T,SS,X,Y,TS,X1,Y1,white):- X1 is X+1, ch_range(X1), getXY0(T,X1,Y,empty), Y1 is Y, remPassant(SS,TS).
movePawn2(T,SS,1,Y,TS,X1,Y1,white):- X1 is 3, getXY0(T,2,Y,empty), getXY0(T,3,Y,empty), Y1 is Y, remPassant(SS,TS0),addPassant(TS0,X1,Y1,TS).
movePawn2(T,SS,X,Y,TS,X1,Y1,white):- X1 is X+1, Y1 is Y-1, ch_range(X1), getXY0(T,X1,Y1,piece(_,black)), remPassant(SS,TS).
movePawn2(T,SS,X,Y,TS,X1,Y1,white):- X1 is X+1, Y1 is Y+1, ch_range(X1), getXY0(T,X1,Y1,piece(_,black)), remPassant(SS,TS).
movePawn2(_,SS,4,Y,TS,X1,Y1,white):- Y1 is Y-1, member(ep(Y1),SS), X1 is 5  , remPassant(SS,TS).
movePawn2(_,SS,4,Y,TS,X1,Y1,white):- Y1 is Y+1, member(ep(Y1),SS), X1 is 5  , remPassant(SS,TS).

%Eliminar posibilidades de captura al paso anteriores
remPassant(SS,TS):-delete(SS,ep(_,_),TS).
addPassant(SS,X,Y,[ep(X,Y)|SS]).
				 
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X-2,Y1 is Y-1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X-1,Y1 is Y-2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X-2,Y1 is Y+1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X-1,Y1 is Y+2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X+2,Y1 is Y+1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X+1,Y1 is Y+2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X+2,Y1 is Y-1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(knight,Color)),X1 is X+1,Y1 is Y-2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).

moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X-2,Y1 is Y-1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X-1,Y1 is Y-2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X-2,Y1 is Y+1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X-1,Y1 is Y+2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X+2,Y1 is Y+1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X+1,Y1 is Y+2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X+2,Y1 is Y-1,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).
moveKnight2(T,X,Y,X1,Y1,Color):-X1 is X+1,Y1 is Y-2,ch_range(X1),ch_range(Y1),avalCell(T,X1,Y1,Color).

moveBishop(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(bishop,Color)),ch_range(Delta),X1 is X+Delta,Y1 is Y+Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopUpRight(T,X,Y,Color,X2,Y2),X1<X2+1,Y1<Y2+1.
moveBishop(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(bishop,Color)),ch_range(Delta),X1 is X+Delta,Y1 is Y-Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopUpLeft(T,X,Y,Color,X2,Y2),X1<X2+1,Y1>Y2-1.
moveBishop(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(bishop,Color)),ch_range(Delta),X1 is X-Delta,Y1 is Y+Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopDownRight(T,X,Y,Color,X2,Y2),X1>X2-1,Y1<Y2+1.
moveBishop(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(bishop,Color)),ch_range(Delta),X1 is X-Delta,Y1 is Y-Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopDownLeft(T,X,Y,Color,X2,Y2),X1>X2-1,Y1>Y2-1.

moveBishop2(T,X,Y,X1,Y1,Color):-limitBishopUpRight(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X+Delta,ch_range(X1),Y1 is Y+Delta,  ch_range(Y1),X1<X2+1,Y1<Y2+1, avalCell(T,X1,Y1,Color).
moveBishop2(T,X,Y,X1,Y1,Color):-limitBishopUpLeft(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X+Delta,ch_range(X1),Y1 is Y-Delta,  ch_range(Y1),X1<X2+1,Y1>Y2-1, avalCell(T,X1,Y1,Color).
moveBishop2(T,X,Y,X1,Y1,Color):-limitBishopDownRight(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X-Delta,ch_range(X1),Y1 is Y+Delta,  ch_range(Y1),X1>X2-1,Y1<Y2+1, avalCell(T,X1,Y1,Color).
moveBishop2(T,X,Y,X1,Y1,Color):-limitBishopDownLeft(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X-Delta, ch_range(X1),Y1 is Y-Delta, ch_range(Y1),X1>X2-1,Y1>Y2-1, avalCell(T,X1,Y1,Color).

moveRook(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(rook,Color)),ch_range(Y1),avalCell(T,X,Y1,Color),limitRookRight(T,X,Y,Color,Y2),limitRookLeft(T,X,Y,Color,Y3),Y1<Y2+1,Y1>Y3-1,X1=X,updateCastlingState(X,Y,SS,TS).
%Vertical
moveRook(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(rook,Color)),ch_range(X1),avalCell(T,X1,Y,Color),limitRookUp(T,X,Y,Color,X2),limitRookDown(T,X,Y,Color,X3),X1<X2+1,X1>X3-1,Y1=Y,updateCastlingState(X,Y,SS,TS).

moveRook2(T,SS,X,Y,TS,X1,Y1,Color):-limitRookRight(T,X,Y,Color,Y2),limitRookLeft(T,X,Y,Color,Y3),ch_range(Y1),Y1<Y2+1,Y1>Y3-1,X1=X,avalCell(T,X,Y1,Color),updateCastlingState(X,Y,SS,TS).
%Vertical
moveRook2(T,SS,X,Y,TS,X1,Y1,Color):-limitRookUp(T,X,Y,Color,X2),limitRookDown(T,X,Y,Color,X3),ch_range(X1),X1<X2+1,X1>X3-1,Y1=Y,avalCell(T,X1,Y,Color),updateCastlingState(X,Y,SS,TS).

updateCastlingState(0,0,SS,TS):-replace(wlc(y),wlc(n),SS,TS),!.
updateCastlingState(0,7,SS,TS):-replace(wsc(y),wsc(n),SS,TS),!.
updateCastlingState(7,0,SS,TS):-replace(blc(y),blc(n),SS,TS),!.
updateCastlingState(7,7,SS,TS):-replace(bsc(y),bsc(n),SS,TS),!.
updateCastlingState(_,_,SS,SS).
disableCastling(white,SS,TS):-replace(wlc(y),wlc(n),SS,AUX),replace(wsc(y),wsc(n),AUX,TS).
disableCastling(black,SS,TS):-replace(blc(y),blc(n),SS,AUX),replace(bsc(y),bsc(n),AUX,TS).

moveQueen(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(queen,Color)),ch_range(Delta),X1 is X+Delta,Y1 is Y+Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopUpRight(T,X,Y,Color,X2,Y2),X1<X2+1,Y1<Y2+1.
moveQueen(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(queen,Color)),ch_range(Delta),X1 is X+Delta,Y1 is Y-Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopUpLeft(T,X,Y,Color,X2,Y2),X1<X2+1,Y1>Y2-1.
moveQueen(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(queen,Color)),ch_range(Delta),X1 is X-Delta,Y1 is Y+Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopDownRight(T,X,Y,Color,X2,Y2),X1>X2-1,Y1<Y2+1.
moveQueen(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(queen,Color)),ch_range(Delta),X1 is X-Delta,Y1 is Y-Delta, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),limitBishopDownLeft(T,X,Y,Color,X2,Y2),X1>X2-1,Y1>Y2-1.
moveQueen(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(queen,Color)),ch_range(Y1),avalCell(T,X,Y1,Color),limitRookRight(T,X,Y,Color,Y2),limitRookLeft(T,X,Y,Color,Y3),Y1<Y2+1,Y1>Y3-1,X1=X.
moveQueen(T,X,Y,X1,Y1,Color):-getXY0(T,X,Y,piece(queen,Color)),ch_range(X1),avalCell(T,X1,Y,Color),limitRookUp(T,X,Y,Color,X2),limitRookDown(T,X,Y,Color,X3),X1<X2+1,X1>X3-1,Y1=Y.

moveQueen2(T,X,Y,X1,Y1,Color):-limitBishopUpRight(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X+Delta,Y1 is Y+Delta, ch_range(X1), ch_range(Y1),X1<X2+1,Y1<Y2+1, avalCell(T,X1,Y1,Color).
moveQueen2(T,X,Y,X1,Y1,Color):-limitBishopUpLeft(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X+Delta,Y1 is Y-Delta, ch_range(X1), ch_range(Y1),X1<X2+1,Y1>Y2-1, avalCell(T,X1,Y1,Color).
moveQueen2(T,X,Y,X1,Y1,Color):-limitBishopDownRight(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X-Delta,Y1 is Y+Delta, ch_range(X1), ch_range(Y1),X1>X2-1,Y1<Y2+1, avalCell(T,X1,Y1,Color).
moveQueen2(T,X,Y,X1,Y1,Color):-limitBishopDownLeft(T,X,Y,Color,X2,Y2),ch_range(Delta),X1 is X-Delta,Y1 is Y-Delta, ch_range(X1), ch_range(Y1),X1>X2-1,Y1>Y2-1, avalCell(T,X1,Y1,Color).
moveQueen2(T,X,Y,X1,Y1,Color):-limitRookRight(T,X,Y,Color,Y2),limitRookLeft(T,X,Y,Color,Y3),ch_range(Y1),Y1<Y2+1,Y1>Y3-1,X1=X,avalCell(T,X,Y1,Color).
moveQueen2(T,X,Y,X1,Y1,Color):-limitRookUp(T,X,Y,Color,X2),limitRookDown(T,X,Y,Color,X3),ch_range(X1),X1<X2+1,X1>X3-1,Y1=Y,avalCell(T,X1,Y,Color).

moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),X1 is X+1,ch_range(X1),avalCell(T,X1,Y,Color),Y1 is Y,disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),X1 is X-1,ch_range(X1),avalCell(T,X1,Y,Color),Y1 is Y,disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),Y1 is Y+1,ch_range(Y1),avalCell(T,X,Y1,Color),X1 is X,disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),Y1 is Y-1,ch_range(Y1),avalCell(T,X,Y1,Color),X1 is X,disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),X1 is X+1,Y1 is Y+1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),X1 is X-1,Y1 is Y+1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),X1 is X+1,Y1 is Y-1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).
moveKing(T,SS,X,Y,TS,X1,Y1,Color):-getXY0(T,X,Y,piece(king,Color)),X1 is X-1,Y1 is Y-1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).

moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-X1 is X+1,ch_range(X1),avalCell(T,X1,Y,Color),Y1 is Y,disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-X1 is X-1,ch_range(X1),avalCell(T,X1,Y,Color),Y1 is Y,disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-Y1 is Y+1,ch_range(Y1),avalCell(T,X,Y1,Color),X1 is X,disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-Y1 is Y-1,ch_range(Y1),avalCell(T,X,Y1,Color),X1 is X,disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-X1 is X+1,Y1 is Y+1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-X1 is X-1,Y1 is Y+1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-X1 is X+1,Y1 is Y-1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).
moveKing2(T,SS,X,Y,TS,X1,Y1,Color):-X1 is X-1,Y1 is Y-1, ch_range(X1), ch_range(Y1), avalCell(T,X1,Y1,Color),disableCastling(Color,SS,TS).

%moveKing(T,SS,0,4,TS,0,6,white):-getXY0(T,0,4,piece(king,white)),member(wsc(y),SS),sc_emptyRange(ZZ),getXY0(T,0,ZZ,empty),sc_range(YY),not(threat(T,SS,0,YY,_,_,black)),disableCastling(white,SS,TS).
%moveKing(T,SS,0,4,TS,0,2,white):-getXY0(T,0,4,piece(king,white)),member(wlc(y),SS),lc_emptyRange(ZZ),getXY0(T,0,ZZ,empty),lc_range(YY),not(threat(T,SS,0,YY,_,_,black)),disableCastling(white,SS,TS).

%moveKing(T,SS,7,4,TS,7,6,black):-getXY0(T,7,4,piece(king,black)),member(bsc(y),SS),sc_emptyRange(ZZ),getXY0(T,7,ZZ,empty),sc_range(YY),not(threat(T,SS,7,YY,_,_,white)),disableCastling(black,SS,TS).
%moveKing(T,SS,7,4,TS,7,2,black):-getXY0(T,7,4,piece(king,black)),member(blc(y),SS),lc_emptyRange(ZZ),getXY0(T,7,ZZ,empty),lc_range(YY),not(threat(T,SS,7,YY,_,_,white)),disableCastling(black,SS,TS).

moveKing2(T,SS,0,4,TS,0,6,white):-member(wsc(y),SS),isFreeSRange(T,0),isFreeSThreat(T,SS,white),disableCastling(white,SS,TS).
moveKing2(T,SS,0,4,TS,2,2,white):-member(wlc(y),SS),isFreeLRange(T,0),isFreeLThreat(T,SS,white),disableCastling(white,SS,TS).

moveKing2(T,SS,7,4,TS,7,6,black):-member(bsc(y),SS),isFreeSRange(T,7),isFreeSThreat(T,SS,black),disableCastling(black,SS,TS).
moveKing2(T,SS,7,4,TS,7,2,black):-member(blc(y),SS),isFreeLRange(T,7),isFreeLThreat(T,SS,black),disableCastling(black,SS,TS).

%Es el mismo getXY0 pero se deja el parametro Y al final para poder usarse en isFreeRange por el mapList
getXY0_fr(Board,Piece,X,Y):-getXY0(Board,X,Y,Piece).
notThreat_ft(T,SS,TX,TY,Player,SX,SY):-not(threat(T,SS,SX,SY,TX,TY,Player)).
    
isFreeSRange(T,Line):-findall(C,sc_emptyRange(C),Y),maplist(getXY0_fr(T,empty,Line),Y).
isFreeLRange(T,Line):-findall(C,lc_emptyRange(C),Y),maplist(getXY0_fr(T,empty,Line),Y).
isFreeSThreat(T,SS,Player):-findall(C,sc_range(C),Y),baseLine(Player,Line),adversary(Player,Adv),maplist(notThreat_ft(T,SS,_,_,Adv,Line),Y).
isFreeLThreat(T,SS,Player):-findall(C,lc_range(C),Y),baseLine(Player,Line),adversary(Player,Adv),maplist(notThreat_ft(T,SS,_,_,Adv,Line),Y).
 
%n Cta